linux: Don't allow partial message raeds from xenstore across
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 27 Feb 2007 13:43:01 +0000 (13:43 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 27 Feb 2007 13:43:01 +0000 (13:43 +0000)
save/restore. This patch is an essential companion to
13519:b4a8000e76db6b4b27341.
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c

index b758c9f676edd9c845ed8cb579e96c4d0e3e2a20..cee8d74e8f2f3dc205da5c603a689a8894d01442 100644 (file)
@@ -137,6 +137,14 @@ int xb_write(const void *data, unsigned len)
        return 0;
 }
 
+int xb_wait_for_data_to_read(void)
+{
+       struct xenstore_domain_interface *intf = xen_store_interface;
+       return wait_event_interruptible(
+               xb_waitq,
+               intf->rsp_cons != intf->rsp_prod);
+}
+
 int xb_read(void *data, unsigned len)
 {
        struct xenstore_domain_interface *intf = xen_store_interface;
@@ -147,9 +155,7 @@ int xb_read(void *data, unsigned len)
                unsigned int avail;
                const char *src;
 
-               rc = wait_event_interruptible(
-                       xb_waitq,
-                       intf->rsp_cons != intf->rsp_prod);
+               rc = xb_wait_for_data_to_read();
                if (rc < 0)
                        return rc;
 
index b54d168cbbd969bb4d404f0cfb58c8e2798ac1c5..95f10e1255a13c0ee2604d9af0d14c593cfb2c37 100644 (file)
@@ -37,6 +37,7 @@ int xb_init_comms(void);
 /* Low level routines. */
 int xb_write(const void *data, unsigned len);
 int xb_read(void *data, unsigned len);
+int xb_wait_for_data_to_read(void);
 int xs_input_avail(void);
 extern struct xenstore_domain_interface *xen_store_interface;
 extern int xen_store_evtchn;
index 23b99b86f5a0fa54d6fbe7358a276c31c91c5d67..69a941d509a06c1a9db43ec4854e4f2778034850 100644 (file)
@@ -150,22 +150,6 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
        return body;
 }
 
-/* Emergency write. */
-void xenbus_debug_write(const char *str, unsigned int count)
-{
-       struct xsd_sockmsg msg = { 0 };
-
-       msg.type = XS_DEBUG;
-       msg.len = sizeof("print") + count + 1;
-
-       mutex_lock(&xs_state.request_mutex);
-       xb_write(&msg, sizeof(msg));
-       xb_write("print", sizeof("print"));
-       xb_write(str, count);
-       xb_write("", 1);
-       mutex_unlock(&xs_state.request_mutex);
-}
-
 void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
 {
        void *ret;
@@ -753,27 +737,38 @@ static int process_msg(void)
        char *body;
        int err;
 
+       err = xb_wait_for_data_to_read();
+       if (err)
+           return err;
+
        msg = kmalloc(sizeof(*msg), GFP_KERNEL);
        if (msg == NULL)
                return -ENOMEM;
 
+       /*
+        * We are now committed to reading an entire message. Partial reads
+        * across save/restore leave us out of sync with the xenstore daemon.
+        */
+       down_read(&xs_state.suspend_mutex);
+
        err = xb_read(&msg->hdr, sizeof(msg->hdr));
        if (err) {
                kfree(msg);
-               return err;
+               goto out;
        }
 
        body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
        if (body == NULL) {
                kfree(msg);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto out;
        }
 
        err = xb_read(body, msg->hdr.len);
        if (err) {
                kfree(body);
                kfree(msg);
-               return err;
+               goto out;
        }
        body[msg->hdr.len] = '\0';
 
@@ -782,7 +777,8 @@ static int process_msg(void)
                                         &msg->u.watch.vec_size);
                if (IS_ERR(msg->u.watch.vec)) {
                        kfree(msg);
-                       return PTR_ERR(msg->u.watch.vec);
+                       err = PTR_ERR(msg->u.watch.vec);
+                       goto out;
                }
 
                spin_lock(&watches_lock);
@@ -806,7 +802,9 @@ static int process_msg(void)
                wake_up(&xs_state.reply_waitq);
        }
 
-       return 0;
+ out:
+       up_read(&xs_state.suspend_mutex);
+       return err;
 }
 
 static int xenbus_thread(void *unused)